package com.cloudlead.common.worker.web;

import com.cloudlead.common.lang.Messages;
import com.cloudlead.common.lang.ObjectStatus;
import com.cloudlead.common.lang.api.SimpleActionRequest;
import com.cloudlead.common.lang.api.SimpleActionResponse;
import com.cloudlead.common.lang.exception.RequestNotAcceptableException;
import com.cloudlead.common.lang.exception.ResourceNotFoundException;
import com.cloudlead.common.lang.utils.ExceptionHelper;
import com.cloudlead.common.worker.client.ApiClient;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.List;

/**
 * Created by dean on 2015/7/29.
 */
public class RemoteServiceRestClient implements RemoteServiceClient {

    private static RemoteServiceRestClient singleInstance;

    private RemoteServiceRestClient() {
    }

    public static synchronized RemoteServiceRestClient getInstance() {
        if (null == singleInstance) {
            singleInstance = new RemoteServiceRestClient();
        }
        return singleInstance;
    }

    public Object executeAction(Class<?> actionFactoryClass, Method method, Object[] params) throws Exception {
        String action = getAction(actionFactoryClass, method.getName());
        String worker = WorkerRegistry.getInstance().findWorker(action);
        if (null == worker) {
            throw new ResourceNotFoundException(Messages.getMessage("worker.NotFound"));
        }

        WorkerInfo workerInfo = WorkerRegistry.getInstance().getWorkerList().get(worker);
        if (null == workerInfo) {
            throw new ResourceNotFoundException(Messages.getMessage("worker.info.NotFound"));
        }

        if (ObjectStatus.disabled.equals(workerInfo.getStatus())) {
            throw new RequestNotAcceptableException(Messages.getMessage("worker.status.disable"));
        }

        SimpleActionRequest request = new SimpleActionRequest();
        Parameter[] parameters = method.getParameters();
        List<String> paramNames = workerInfo.getActions().get(action);
        for (int i = 0; i < parameters.length; i++) {
            String name = paramNames.get(i);
            request.addContent(name, params[i]);
        }
        ApiClient apiClient = new ApiClient(workerInfo.getWorkerIp(), workerInfo.getWorkerPort());
        SimpleActionResponse<?> simpleActionResponse = apiClient.executeRequest(action, request, method.getReturnType());
        if (simpleActionResponse.isSuccess()) {
            return simpleActionResponse.getContent();
        } else {
            throw ExceptionHelper.toException(simpleActionResponse.getCode(), simpleActionResponse.getMessage());
        }

    }

    private String getAction(Class<?> actionFactory, String method) {
        return WorkerRegistry.getInstance().findModule(actionFactory.getTypeName()) + "@" + method;
    }

}
